package com.far.game.xiuzhen.gm.web.api.admin;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.far.game.xiuzhen.common.database.entity.*;

import com.far.game.xiuzhen.common.database.entity.Vo.SelectVo;
import com.far.game.xiuzhen.common.database.entity.Vo.admin.PartnerSkillVo;
import com.far.game.xiuzhen.common.database.entity.Vo.admin.SkillBufVo;
import com.far.game.xiuzhen.common.database.entity.Vo.admin.SkillVo;
import com.far.game.xiuzhen.common.enums.game.*;
import com.far.game.xiuzhen.common.enums.game.buf.*;
import com.far.game.xiuzhen.common.enums.game.skill.PassiveTriggerEnums;
import com.far.game.xiuzhen.common.enums.game.skill.UseSkillNeedPropEnums;
import com.far.game.xiuzhen.common.utils.EnumUtil;
import com.far.game.xiuzhen.gm.web.BaseController;
import com.far.game.xiuzhen.service.*;
import com.far.tools.net.http.ReqParamWrapper;
import com.far.tools.net.http.transfer.QueryColumn;
import com.far.tools.net.http.transfer.ResultData;
import com.mysql.jdbc.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author mike
 * @since 2022-07-15
 */
@Api(tags = "角色技能层")
@RestController
@RequestMapping("/api/admin/role/skill")
public class RoleSkillController extends BaseController {


    @Autowired
    @Qualifier("skillBufsServiceImpl")
    private ISkillBufsService iSkillBufsService;

    @Autowired
    @Qualifier("skillsServiceImpl")
    private ISkillsService iSkillsService;

    @Autowired
    @Qualifier("serversServiceImpl")
    private IServersService iServersService;


    @Autowired
    @Qualifier("partnerServiceImpl")
    private IPartnerService iPartnerService;

    @Autowired
    @Qualifier("partnerSkillServiceImpl")
    private IPartnerSkillService iPartnerSkillService;

    /**
     * 技能表数据添加
     */

    @ApiOperation(value = "技能添加", notes = "新增技能数据")
    @PostMapping(value = "skill-add")
    private ResultData<String> skillAdd(@RequestBody Skills skills) {
        skills.setUpdateBy(this.getVisitor().getUserName());
        skills.setCreateBy(this.getVisitor().getUserName());
        if (iSkillsService.save(skills)) {
            return ResultData.ok("添加成功");
        }
        return ResultData.error("添加失败");
    }

    /**
     * 技能表数据更新
     */
    @ApiOperation(value = "技能更新", notes = "技能数据更新")
    @PostMapping(value = "skill-update")
    private ResultData<String> skillUpdate(@RequestBody Skills skills) {
        skills.setUpdateBy(this.getVisitor().getUserName());
        if (iSkillsService.updateById(skills)) {
            return ResultData.ok("更新成功");
        }
        return ResultData.error("更新失败");
    }


    /**
     * 技能表数据删除
     */
    @ApiOperation(value = "技能删除", notes = "技能数据删除传入ID")
    @ApiImplicitParam(name = "tid", value = "ID", required = true, paramType = "query", dataType = "Integer")
    @GetMapping(value = "skill-remove")
    private ResultData<String> skillRemove(@RequestParam("tid") Integer tid) {
       Skills skills=  iSkillsService.lambdaQuery().eq(Skills::getTid,tid).one();
        if (iSkillsService.removeById(tid)) {
            return ResultData.ok("删除成功");
        }
        return ResultData.error("删除失败");
    }


    /**
     * 获取技能信息
     */
    @ApiOperation(value = "获取技能信息", notes = "传入技能唯一tid")
//    @ApiImplicitParam(name = "tid", value = "ID", required = true, paramType = "query", dataType = "Integer")
    @PostMapping(value = "get-skill-info")
    private ResultData<Skills> getSkillInfo(@RequestBody Skills tid) {
        return ResultData.ok(iSkillsService.lambdaQuery().eq(Skills::getTid, tid.getTid()).one());
    }


    /**
     * 技能表数据查询
     */
    @ApiOperation(value = "技能查询", notes = "ReqParamWrapper")
    @PostMapping(value = "skill-query")
    public ResultData<?> skillQuery(@RequestBody ReqParamWrapper<Skills, String> reqParamWrapper) {

        IPage<Skills> iPage = reqParamWrapper.pageLists(iSkillsService);
        if (iPage.getRecords().size() == 0) {
            return ResultData.ok("暂无数据");
        }
        List<Skills> skills = iPage.getRecords();
        List<SkillVo> voList = new ArrayList<>();
        for (Skills data : skills) {
            SkillVo skillVo = BeanUtil.copyProperties(data, SkillVo.class).bulid();
            Servers servers = iServersService.lambdaQuery().eq(Servers::getTid, data.getDomainId()).one();
            if (ObjectUtil.isEmpty(servers)) {
                return ResultData.error(String.format("%s<%s> 没有绑定正确的区服！", skillVo.getSkillName(), skillVo.getSid()));
            }


            Servers servers1 = iServersService.lambdaQuery().eq(Servers::getTid, servers.getParentTid()).one();
            if (ObjectUtil.isEmpty(servers1)) {
                skillVo.setDomainTidStr(servers.getServerName() + "," + "未绑定服务器");
            } else {
                skillVo.setDomainTidStr(servers.getServerName() + "," + servers1.getServerName());
            }
            voList.add(skillVo);
        }
        IPage<SkillVo> page = new Page<>();
        page.setRecords(voList);
        page.setCurrent(iPage.getCurrent());
        page.setSize(iPage.getSize());
        page.setTotal(iPage.getTotal());

        return ResultData.ok(page);

    }

    /**
     * 技能表数据查询
     */
    @ApiOperation(value = "查询buf追加技能列表", notes = "传入buf技能对象的tid")
    @PostMapping(value = "sadd-skill-list-query")
    private ResultData<List<SkillVo>> saddSkillListQuery(@RequestBody SkillBufs tid) {
        SkillBufs skillBufs = iSkillBufsService.lambdaQuery().eq(SkillBufs::getTid, tid.getTid()).one();
        if (ObjectUtil.isEmpty(skillBufs.getSaddRef())) {
            return ResultData.error("暂无数据");
        }
        String[] strings = skillBufs.getSaddRef().split(",");
        List<SkillVo> voList = new ArrayList<>();
        List<Skills> list = iSkillsService.lambdaQuery().in(Skills::getSid, strings).list();
        if (ObjectUtil.isEmpty(list)) {
            return ResultData.error("技能buf追加技能错误：" + strings);
        }
        for (Skills data : list) {
            SkillVo skillVo = BeanUtil.copyProperties(data, SkillVo.class).bulid();
            Servers servers = iServersService.lambdaQuery().eq(Servers::getTid, skillVo.getDomainId()).one();
            Servers servers1 = iServersService.lambdaQuery().eq(Servers::getTid, servers.getParentTid()).one();
            if (ObjectUtil.isEmpty(servers1)) {
                skillVo.setDomainTidStr(servers.getServerName() + "," + "未绑定服务器");
            } else {
                skillVo.setDomainTidStr(servers.getServerName() + "," + servers1.getServerName());
            }
            voList.add(skillVo);
        }
        return ResultData.ok(voList);


    }


    /**
     * 技能表数据查询
     */
    @ApiOperation(value = "子技能查询", notes = "技能对象的tid")
    @GetMapping(value = "son-skill-query")
    private ResultData<List<Skills>> sonSkillQuery(@RequestParam String sonSkill) {

        String[] strings = sonSkill.split(",");
        List<Skills> list = iSkillsService.lambdaQuery().in(Skills::getSid, strings).list();
        return ResultData.ok(list);
    }


    /**
     * 技能表数据查询
     */
    @ApiOperation(value = "查询主技能的子技能", notes = "默认按照主技能的tid查询")
    @PostMapping(value = "son-skill-query-by-tid")
    private ResultData<IPage<SkillVo>> sonSkillQueryByTid(@RequestBody ReqParamWrapper<Skills, String> reqParamWrapper) {


        List<String> subSkillSid = new ArrayList<>();
        List<Skills> subSkills = null;

        Optional<QueryColumn> queryColumn = reqParamWrapper.getColumns().stream().filter(e -> {
            return e.getName().equals("tid");
        }).findFirst();

        if (!queryColumn.isPresent()) {
            return ResultData.error("缺少条件tid");
        }

        iSkillsService.lambdaQuery().eq(Skills::getTid, queryColumn.get().getValue()).list().stream().forEach(e -> {
            if (e.getCombineSkLs().indexOf(",") < 0) {//单独的一个子技能
                subSkillSid.add(e.getCombineSkLs());
            } else {
                Stream.of(e.getCombineSkLs().split(",")).forEach(e2 -> {
                    subSkillSid.add(e2);
                });
            }
        });
        //IPage<Skills> datas =
        LambdaQueryChainWrapper<Skills> lambdaQueryChainWrapper = new LambdaQueryChainWrapper<>(iSkillsService.getBaseMapper());
        List<SkillVo> datas = lambdaQueryChainWrapper.in(Skills::getSid, subSkillSid)
                .page(reqParamWrapper.getPageHodler()).getRecords()
                .stream().map(e -> {
                    return BeanUtil.copyProperties(e, SkillVo.class).bulid();
                }).collect(Collectors.toList());
        IPage<SkillVo> resData = new Page<SkillVo>(reqParamWrapper.getCurrent(), reqParamWrapper.getSize()).setRecords(datas);
        if (CollectionUtil.isEmpty(resData.getRecords())) {
            return ResultData.error("暂无数据");
        }
        return ResultData.ok(resData);
    }


    /**
     * 技能伙伴关联表
     */
    @ApiOperation(value = "技能伙伴关联表导入", notes = "导入技能关联伙伴信息")
    @PostMapping(value = "skill-connection-partner")
    private ResultData<String> skillConnectionPartner(MultipartFile file) {

        ExcelReader reader = null;
        try {
            reader = ExcelUtil.getReader(file.getInputStream());
            HashMap<String, String> headerAlias = new HashMap<>(2);
            headerAlias.put("品质", "quality");
            headerAlias.put("角色", "partnerName");
            headerAlias.put("技能", "skillName");

            reader.setHeaderAlias(headerAlias);
            List<PartnerSkillVo> list = reader.read(0, 0, PartnerSkillVo.class);
            List<PartnerSkill> partnerSkills = list.stream().map(i -> {
                PartnerSkill partnerSkill = new PartnerSkill();
                Partner partner = iPartnerService.lambdaQuery().eq(Partner::getQuality, i.getQuality()).eq(Partner::getPartnerName, i.getPartnerName()).one();
                String[] qul = i.getSkillName().split("-");

                if (qul[1].equals("1")) {
                    i.setSkillName(qul[0] + "-天");
                } else if (qul[1].equals("2")) {
                    i.setSkillName(qul[0] + "-地");
                } else if (qul[1].equals("3")) {
                    i.setSkillName(qul[0] + "-玄");
                } else if (qul[1].equals("4")) {
                    i.setSkillName(qul[0] + "-皇");
                } else if (qul[1].equals("5")) {
                    i.setSkillName(qul[0] + "-凡");
                }
                Skills skills = iSkillsService.lambdaQuery().eq(Skills::getSkillName, i.getSkillName()).one();
                partnerSkill.setSkillSid(skills.getSid());
                partnerSkill.setPartnerSid(partner.getSid().toString());
                partnerSkill.setDomainTid(skills.getDomainId());
                return partnerSkill;
            }).collect(Collectors.toList());
            iPartnerSkillService.saveBatch(partnerSkills);
            return ResultData.ok("导入完成");
        } catch (IOException e) {
            if (ObjectUtil.isNotEmpty(reader)) reader.close();
            throw new RuntimeException(e);
        }

    }


    @ApiOperation(value = "技能导入", notes = "技能导入")
    @PostMapping("/import")
    public ResultData importExcel(MultipartFile file) {
        ExcelReader reader = null;
        try {
            reader = ExcelUtil.getReader(file.getInputStream());

            HashMap<String, String> headerAlias = new HashMap<>(1);
            headerAlias.put("skill_name", "skillName");
//            headerAlias.put("passivity", "passivity");
//            headerAlias.put("passivity_trigger_on_type", "passivityTriggerOnType");
//            headerAlias.put("is_combine", "isCombine");
//            headerAlias.put("combine_sk_ls", "combineSkLs");
//            headerAlias.put("expend_prop", "expendProp");
//            headerAlias.put("expend_val", "expendVal");
            reader.setHeaderAlias(headerAlias);
            List<Skills> list = reader.read(0, 0, Skills.class);
            //保存

            Long max;
            List<Skills> skillsList = iSkillsService.list();
            if (ObjectUtil.isEmpty(skillsList) || skillsList.size() <= 0) {
                max = 100000000000L;
            } else {
                max = Long.valueOf(skillsList.get(0).getSid());
                for (int i = 0; i < skillsList.size(); i++) {
                    if (max < Long.valueOf(skillsList.get(i).getSid())) {
                        max = Long.valueOf(skillsList.get(i).getSid());
                    }
                }
            }
            List<Skills> skillsLists = new ArrayList<>();
            for (Skills skills : list) {
                Long sum = max++;
                Skills skillsData = BeanUtil.copyProperties(skills, Skills.class);

                String[] qul = skillsData.getSkillName().split("-");

                if (qul[1].equals("1")) {
                    skillsData.setSkillName(qul[0] + "-天");
                } else if (qul[1].equals("2")) {
                    skillsData.setSkillName(qul[0] + "-地");
                } else if (qul[1].equals("3")) {
                    skillsData.setSkillName(qul[0] + "-玄");
                } else if (qul[1].equals("4")) {
                    skillsData.setSkillName(qul[0] + "-皇");
                } else if (qul[1].equals("5")) {
                    skillsData.setSkillName(qul[0] + "-凡");
                }


                skillsData.setSid(sum.toString());


                skillsData.setExpendProp(UseSkillNeedPropEnums.NENG_LIANG.getVal());
                skillsData.setExpendVal(0);
                //是否是组合技能
                skillsData.setIsCombine(0);
                //是否是被动技能
                skillsData.setPassivity(0);
                skillsData.setPassivityTriggerOnType(PassiveTriggerEnums.NONE.getVal());

                skillsData.setUpdateBy(this.getVisitor().getUserName());
                skillsData.setCreateBy(this.getVisitor().getUserName());
                skillsData.setDomainId(1);
                skillsLists.add(skillsData);
            }
            Set<Skills> skillsSet = new TreeSet<>((o1, o2) -> o1.getSkillName().compareTo(o2.getSkillName()));
            skillsSet.addAll(skillsLists);
            List<Skills> skills = new ArrayList<>(skillsSet);

            iSkillsService.saveBatch(skills);
            return ResultData.ok("导入成功");
        } catch (IOException e) {
            if (ObjectUtil.isNotEmpty(reader)) reader.close();
            e.printStackTrace();
        }
        return ResultData.error("导入失败！");
    }


    /**
     * 技能BUFF表数据新增
     */
    @ApiOperation(value = "技能buff添加", notes = "添加技能BUFF数据")
    @PostMapping(value = "skill-bufs-add")
    private ResultData<String> skillBufsAdd(@RequestBody SkillBufs skillBufs) {


        skillBufs.setCreateBy(this.getVisitor().getUserName());
        skillBufs.setUpdateBy(this.getVisitor().getUserName());
        if (iSkillBufsService.save(skillBufs)) {

            return ResultData.ok("添加成功");
        }
        return ResultData.error("添加失败");
    }

    /**
     * 技能BUFF表数据更新
     */
    @ApiOperation(value = "技能buff更新", notes = "技能buff数据更新")
    @PostMapping(value = "skill-bufs-update")
    private ResultData<String> skillBufsUpdate(@RequestBody SkillBufs skillBufs) {

        skillBufs.setUpdateBy(this.getVisitor().getUserName());
        if (iSkillBufsService.updateById(skillBufs)) {
            return ResultData.ok("更新成功");
        }
        return ResultData.error("更新失败");
    }

    /**
     * 技能BUFF表数据删除
     */
    @ApiOperation(value = "技能buff删除", notes = "技能buff数据删除")
    @ApiImplicitParam(name = "tid", value = "ID", required = true, paramType = "query", dataType = "Integer")
    @GetMapping(value = "skill-bufs-remove")
    private ResultData<String> skillBufsRemove(@RequestParam("tid") Integer tid) {
        if (iSkillBufsService.removeById(tid)) {
            return ResultData.ok("删除成功");
        }
        return ResultData.error("删除失败");
    }

    /**
     * 技能BUFF表数据查询
     */
    @ApiOperation(value = "技能buff查询", notes = "ReqParamWrapper")
    @PostMapping(value = "skill-bufs-query")
    private ResultData<IPage<SkillBufVo>> skillBufsQuery(@RequestBody ReqParamWrapper<SkillBufs, String> reqParamWrapper) {
        IPage<SkillBufs> iPage = reqParamWrapper.pageLists(iSkillBufsService);
        if (iPage.getRecords().size() == 0) {
            return ResultData.error("暂无数据");
        }
        List<SkillBufs> skillBufs = iPage.getRecords();
        List<SkillBufVo> voList = new ArrayList<>();
        for (SkillBufs bufs : skillBufs) {
            SkillBufVo skillBufVo = BeanUtil.copyProperties(bufs, SkillBufVo.class).bulid();
            voList.add(skillBufVo);
        }
        IPage<SkillBufVo> skillBufVoIPage = new Page<>();
        skillBufVoIPage.setCurrent(iPage.getCurrent());
        skillBufVoIPage.setSize(iPage.getSize());
        skillBufVoIPage.setTotal(iPage.getTotal());
        skillBufVoIPage.setRecords(voList);
        return ResultData.ok(skillBufVoIPage);
    }


    /**
     * 技能下拉列表
     */
    @ApiOperation(value = "下拉列表集合", notes = "查询所有的下拉列表")
    @PostMapping(value = "drop-down-list")
    private ResultData<List<SelectVo>> dropDownList() {

        List<SelectVo> selectVoList = new ArrayList<>();
        //BUF类型
        selectVoList.add(EnumUtil.toSelectVo(BufTypeEnums.values(), SelectVoOfEnumTypeEnum.BUF_TYPE));
        //变化类型
        selectVoList.add(EnumUtil.toSelectVo(ChangeTypeEnums.values(), SelectVoOfEnumTypeEnum.CHANGE_TYPE));
        //变化值类型
        selectVoList.add(EnumUtil.toSelectVo(ChangeValTypeEnums.values(), SelectVoOfEnumTypeEnum.CHANGE_VAL_TYPE));
        //作用周期
        selectVoList.add(EnumUtil.toSelectVo(CycleTypeEnums.values(), SelectVoOfEnumTypeEnum.CYCLE_TYPE));
        //作用范围
        selectVoList.add(EnumUtil.toSelectVo(FindDomainEnums.values(), SelectVoOfEnumTypeEnum.FIND_DOMAIN));
        //作用属性检测
        selectVoList.add(EnumUtil.toSelectVo(FindPropEnums.values(), SelectVoOfEnumTypeEnum.FIND_PROP));
        //输出参考
        selectVoList.add(EnumUtil.toSelectVo(RefTargetEnums.values(), SelectVoOfEnumTypeEnum.REF_TARGET));
        //执行结果
        selectVoList.add(EnumUtil.toSelectVo(ResultTypeEnum.values(), SelectVoOfEnumTypeEnum.RESULT_TYPE));
        //buf出招顺序
        selectVoList.add(EnumUtil.toSelectVo(HitOrderEnums.values(), SelectVoOfEnumTypeEnum.ORDER_IDX));
        //输出参考
        selectVoList.add(EnumUtil.toSelectVo(RefTargetEnums.values(), SelectVoOfEnumTypeEnum.REF_TARGET));
        //获取种族
        selectVoList.add(EnumUtil.toSelectVo(RaceEnums.values(), SelectVoOfEnumTypeEnum.RACE_TYPE));
        //职业类型
        selectVoList.add(EnumUtil.toSelectVo(JobEnums.values(), SelectVoOfEnumTypeEnum.JOB_TYPE));
        return ResultData.ok(selectVoList);
    }


    /**
     * 伙伴技能链表批量保存
     */
    @ApiOperation(value = "批量保存伙伴关联技能", notes = "保存伙伴关联技能接口")
    @PostMapping(value = "partner-skill-add")
    private ResultData<String> partnerSkillAdd(@RequestBody List<PartnerSkill> partnerSkill) {

        if (iPartnerSkillService.saveBatch(partnerSkill)) {
            return ResultData.ok("保存成功");
        }
        return ResultData.error("保存失败");
    }


    /**
     * 伙伴查询技能信息
     */
    @ApiOperation(value = "伙伴技能关联表查询技能", notes = "根据传入伙伴固定编号查询绑定技能")
    @GetMapping(value = "partner-query-skill")
    private ResultData<List<SkillVo>> partnerQuerySkill(@RequestParam Integer tid) {
       Partner partner =  iPartnerService.lambdaQuery().eq(Partner::getTid,tid).one();
       if(ObjectUtil.isEmpty(partner)){
           return ResultData.error("伙伴表没有添加此伙伴");
       }
        List<PartnerSkill> partnerSkills = iPartnerSkillService.lambdaQuery().eq(PartnerSkill::getPartnerSid, partner.getSid()).list();
        if (ObjectUtil.isNull(partnerSkills)) {
            return ResultData.error("暂无绑定技能");
        }
        List<SkillVo> skillVos = partnerSkills.stream().map(e -> {

            Skills skills = iSkillsService.lambdaQuery().eq(Skills::getSid, e.getSkillSid()).one();
            SkillVo skillVo =  BeanUtil.copyProperties(skills, SkillVo.class).bulid();
                   skillVo.setPartnerSkillTid(e.getTid());
            return skillVo;
        }).collect(Collectors.toList());
        skillVos.stream().map(e -> {
            Servers servers = iServersService.lambdaQuery().eq(Servers::getTid, e.getDomainId()).one();
            Servers servers1 = iServersService.lambdaQuery().eq(Servers::getTid, servers.getParentTid()).one();
            if (ObjectUtil.isEmpty(servers)) {
                return ResultData.error(String.format("%s<%s> 没有绑定正确的区服！", e.getSkillName(), e.getSid()));
            } else {
                if (ObjectUtil.isEmpty(servers1)) {
                    e.setDomainTidStr(servers.getServerName() + "," + "未绑定服务器");
                } else {
                    e.setDomainTidStr(servers.getServerName() + "," + servers1.getServerName());
                }
            }
            return e;
        }).collect(Collectors.toList());

        return ResultData.ok(skillVos);
    }

    /**
     * 伙伴技能关联表删除
     */
    @ApiOperation(value = "伙伴技能关联表删除", notes = "传入tid删除技能关联信息")
    @ApiImplicitParam(name = "tid", value = "ID", required = true, paramType = "query", dataType = "Integer")
    @GetMapping(value = "partner-skill-remove")
    private ResultData<String> partnerSkillRemove(@RequestParam("tid") Integer tid) {
        if (iPartnerSkillService.removeById(tid)) {
            return ResultData.ok("删除成功");
        }
        return ResultData.error("删除失败");
    }

}

